package device

import (
	"context"
	"encoding/binary"
	"fpga-vboard/pins"
	"fpga-vboard/protocol"

	"github.com/wailsapp/wails/v2/pkg/runtime"
)

const (
	Nixie_SCL       = "nixie_scl"
	Nixie_SDA_IN    = "nixie_sda_in"
	Nixie_SDA_OUT   = "nixie_sda_out"
	Reg_on_off_ADDR = 1
	Reg_Number_ADDR = 2
)

func init() {
	config := &NixieTubeConfig{
		DeviceInfo: DeviceInfo{
			Id:   NixieTube_DEFAULT,
			Type: NixieTube,
			InputPins: []*pins.PinDef{
				{
					Name:      Nixie_SDA_IN,
					BitSize:   1,
					Direction: pins.PinDirectionInput,
				},
				{
					Name:      Nixie_SCL,
					BitSize:   1,
					Direction: pins.PinDirectionInput,
				},
			},
			OutputPins: []*pins.PinDef{
				{
					Name:      Nixie_SDA_OUT,
					BitSize:   1,
					Direction: pins.PinDirectionOutput,
				},
			},
			Name:       "Nixie Tube",
			IsOptional: true,
			Enable:     false,
		},
		IICConfig: &protocol.IICConfig{
			DevAddr: 0x1,
		},
	}
	RegisterDev(config)
}

type NixieTubeDev struct {
	*DeviceBase
	iicSlaver  *protocol.IICSlaver
	lastNumber uint32
	lastOnOff  byte
}

func NewNixieTubeDev(config *NixieTubeConfig) *NixieTubeDev {
	return &NixieTubeDev{
		DeviceBase: &DeviceBase{
			Config: config,
		},
		iicSlaver: protocol.NewIICSlaver(config.IICConfig),
	}
}

func (n *NixieTubeDev) Start(ctx context.Context) error {
	// show on-off register
	n.iicSlaver.Regs[Reg_on_off_ADDR] = &protocol.IICRegInfo{
		RegAddr:    Reg_on_off_ADDR,
		RegByteLen: 1,
		RegValues:  make([]byte, 1),
	}
	// show number register
	n.iicSlaver.Regs[Reg_Number_ADDR] = &protocol.IICRegInfo{
		RegAddr:    Reg_Number_ADDR,
		RegByteLen: 4,
		RegValues:  make([]byte, 4),
	}
	return nil
}

func (n *NixieTubeDev) Run(ctx context.Context) {
	n.iicSlaver.Run(n.GetPinBool(Nixie_SCL), n.GetPinBool(Nixie_SDA_IN))
	if n.iicSlaver.IsOutSet {
		n.SetPinBool(Nixie_SDA_OUT, n.iicSlaver.OutSDA)
	}
	if n.iicSlaver.IsComplete {
		if n.iicSlaver.Regs[Reg_on_off_ADDR].RegValues[0] > 0 {
			newNumber := binary.LittleEndian.Uint32(n.iicSlaver.Regs[Reg_Number_ADDR].RegValues)
			if newNumber != n.lastNumber {
				n.lastNumber = newNumber
				runtime.EventsEmit(ctx, "nixie_tube_number", n.lastNumber)
			}
		} else if n.lastOnOff > 0 {
			n.lastOnOff = n.iicSlaver.Regs[Reg_on_off_ADDR].RegValues[0]
			runtime.EventsEmit(ctx, "nixie_tube_number", -1) // turn off
		}
	}
}
